//============================================================================
// Copyright (C) 2013 Brett R. Jones
//
// Issued to public domain 2013
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================
#ifdef WIN_PLATFORM

#include "VxShortcut.h"
#include "vx_debug.h"

#include "winnls.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"

//============================================================================
HRESULT VxCreateShortcut(	std::string csLinkName, //Full path to link ( link name should not have the .lnk extention )
												//example C:\\windows\\Desktop\\MyApp
							std::string csPathToExe, //path to exe to run when link is run
							std::string csLinkDesc	) //description of link
{
	HRESULT hres;
	IShellLink* psl = 0;

	std::string csLinkPath = csLinkName;

	hres = CoCreateInstance(CLSID_ShellLink, 
						NULL, 
						CLSCTX_INPROC_SERVER,
						IID_IShellLink, 
						(LPVOID*) &psl);
	if (SUCCEEDED(hres))
	{
		IPersistFile* ppf;

		psl->SetPath( csPathToExe.c_str() );
		psl->SetDescription( csLinkDesc.c_str() );

		hres = psl->QueryInterface( IID_IPersistFile, (LPVOID *) &ppf);

		if (SUCCEEDED(hres))
		{
			csLinkPath += ".lnk";  // Important !!!

			WORD wsz[MAX_PATH];
			MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, csLinkPath.c_str(), -1, (LPWSTR)wsz, MAX_PATH);

			hres = ppf->Save((LPCOLESTR)wsz, TRUE);
			if (hres != S_OK )
				log_msg( LOG_ERROR, "IPersistFile->Save() Error" );
			
			ppf->Release();
		}
		psl->Release();
	}
	else
	{
		if( 0x800401f0 == hres )
		{
			log_msg( LOG_ERROR, "Must call AfxOleInit() before calling VxCreateShortcut.. Call AfxOleInit()" );
		}
		if( S_OK == hres )
		{
			log_msg( LOG_ERROR, "An instance of the specified object class was successfully created. \n");
		}
		else if( REGDB_E_CLASSNOTREG == hres )
		{
			log_msg( LOG_ERROR, "A specified class is not registered in the registration database. Also can indicate that the type of server you requested in the CLSCTX enumeration is not registered or the values for the server types in the registry are corrupt. \n");
		}
		else if( CLASS_E_NOAGGREGATION  == hres )
		{
			log_msg( LOG_ERROR, "This class cannot be created as part of an aggregate. \n");
		}
		else
		{
			log_msg( LOG_ERROR, "Unknown error\n");
		}

	}
	return hres;
}
//============================================================================
HRESULT VxResolveShortcut(	HWND hwnd, //handle to window of caller
							LPCSTR pszShortcutFile, //.lnk file
							LPSTR pszPath) //return path to target file
{ 
	HRESULT hres;
	IShellLink* psl;
	char szGotPath[MAX_PATH];
//	char szDescription[MAX_PATH];
	WIN32_FIND_DATA wfd;
	
	*pszPath = 0;   // assume failure
	
	// Get a pointer to the IShellLink interface.
	hres = CoCreateInstance(	CLSID_ShellLink, 
		NULL, 
		CLSCTX_INPROC_SERVER,
		IID_IShellLink, 
		(void **)&psl);
	if (SUCCEEDED(hres))
	{
		IPersistFile* ppf;
		
		// Get a pointer to the IPersistFile interface.
		hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
		if (SUCCEEDED(hres))
		{
			WORD wsz[MAX_PATH];
			
			// Ensure string is Unicode.
			MultiByteToWideChar(CP_ACP, 0, pszShortcutFile, -1, (LPWSTR)wsz,
				MAX_PATH);
			
			// Load the shell link.
			hres = ppf->Load((LPCOLESTR)wsz, STGM_READ);
			if (SUCCEEDED(hres))
			{
				// Resolve the link.
				hres = psl->Resolve(hwnd, SLR_ANY_MATCH);
				
				if (SUCCEEDED(hres))
				{
					strcpy(szGotPath, pszShortcutFile);
					// Get the path to the link target.
					hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA *)&wfd, 
						SLGP_UNCPRIORITY  );
					if( !SUCCEEDED(hres) )
					{	
						log_msg( LOG_ERROR, "GetPath failed!\n" );
					}
					else
					{
						strcpy( pszPath, szGotPath );
					}
					// works but I dont need the description
					// Get the description of the target.         
//					hres = psl->GetDescription(szDescription, MAX_PATH);
//					if (!SUCCEEDED(hres))
//					{
//						AfxMessageBox("GetDescription failed!");
//					}
				}
			}
			// Release pointer to IPersistFile interface.
			ppf->Release();
		}
		// Release pointer to IShellLink interface.
		psl->Release();
	}
	else
	{
		if( 0x800401f0 == hres )
		{
			log_msg( LOG_ERROR, "Must call AfxOleInit() before calling VxResolveShortcut.. Call AfxOleInit()" );
		}
		if( S_OK == hres )
		{
			log_msg( LOG_ERROR, "An instance of the specified object class was successfully created. \n");
		}
		else if( REGDB_E_CLASSNOTREG == hres )
		{
			log_msg( LOG_ERROR, "A specified class is not registered in the registration database. Also can indicate that the type of server you requested in the CLSCTX enumeration is not registered or the values for the server types in the registry are corrupt. \n");
		}
		else if( CLASS_E_NOAGGREGATION  == hres )
		{
			log_msg( LOG_ERROR, "This class cannot be created as part of an aggregate. \n");
		}
		else
		{
			log_msg( LOG_ERROR, "Unknown error\n");
		}
	}
	return hres;
} 

#endif // WIN_PLATFORM
